import 'package:dio/dio.dart';
import 'package:dio_smart_retry/dio_smart_retry.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:go_router/go_router.dart';
import '../app_config.dart';
import '../auth/auth_service.dart';
import '../router/app_router.dart';
import 'api_response.dart';

class HttpClient {
  static final HttpClient _instance = HttpClient._internal();
  late Dio _dio;

  factory HttpClient() {
    return _instance;
  }

  HttpClient._internal() {
    _dio = Dio(
      BaseOptions(
        baseUrl: AppConfig.apiBaseUrl,
        connectTimeout: const Duration(milliseconds: AppConfig.connectTimeout),
        receiveTimeout: const Duration(milliseconds: AppConfig.receiveTimeout),
        headers: {'Content-Type': 'application/json'},
      ),
    );
    _dio.options.validateStatus = (status) {
      return status != null && status >= 200 && status < 500;
    };
    _initInterceptors();
    _setupRetry();
  }

  void _setupRetry() {
    _dio.interceptors.add(
      RetryInterceptor(
        dio: _dio,
        logPrint: print,
        retries: AppConfig.maxRetries,
        retryDelays: List.generate(
          AppConfig.maxRetries,
          (index) => AppConfig.retryInterval * (index + 1),
        ),
      ),
    );
  }

  void _initInterceptors() {
    // 添加日志拦截器，仅在开发模式下输出日志
    if (AppConfig.isDevelopment) {
      _dio.interceptors.add(
        LogInterceptor(
          requestBody: true,
          responseBody: true,
          logPrint: (Object object) {
            print('🌐 [Dio] $object');
          },
        ),
      );
    }

    _dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (options, handler) async {
          final authService = AuthService();
          final accessToken = await authService.getAccessToken();

          if (accessToken != null) {
            // 检查 access token 是否即将过期
            if (await authService.shouldRefreshToken()) {
              // 使用 refresh token 刷新 token
              final refreshed = await authService.refreshToken();
              if (refreshed) {
                final newAccessToken = await authService.getAccessToken();
                options.headers['Authorization'] = 'Bearer $newAccessToken';
              }
            } else {
              options.headers['Authorization'] = 'Bearer $accessToken';
            }
          }
          return handler.next(options);
        },
        onResponse: (response, handler) {
          return handler.next(response);
        },
        onError: (DioException e, handler) async {
          String message = '';
          switch (e.type) {
            case DioExceptionType.connectionTimeout:
              message = '连接超时';
              break;
            case DioExceptionType.receiveTimeout:
              message = '响应超时';
              break;
            case DioExceptionType.badResponse:
              switch (e.response?.statusCode) {
                case 401:
                  final authService = AuthService();
                  // 尝试刷新token
                  if (await authService.refreshToken()) {
                    // 刷新token成功，重试请求
                    final newAccessToken = await authService.getAccessToken();
                    if (newAccessToken != null) {
                      e.requestOptions.headers['Authorization'] = 'Bearer $newAccessToken';
                      try {
                        final response = await _dio.fetch(e.requestOptions);
                        return handler.resolve(response);
                      } catch (retryError) {
                        message = '请求重试失败';
                      }
                    }
                  }
                  // 刷新token失败或重试失败，清除token并跳转到登录页
                  message = '登录已过期，请重新登录';
                  await authService.logout();
                  if (AppRouter.router.routerDelegate.navigatorKey.currentContext != null) {
                    GoRouter.of(AppRouter.router.routerDelegate.navigatorKey.currentContext!).go('/login');
                  }
                  break;
                case 403:
                  message = '没有权限访问';
                  break;
                case 404:
                  message = '请求的资源不存在';
                  break;
                case 500:
                  message = '服务器错误';
                  break;
                default:
                  message = '请求失败';
              }
              break;
            default:
              message = '网络错误';
          }
          // EasyLoading.showError(message);
          return handler.next(e);
        },
      ),
    );
  }

  Future<ApiResponse<T>> get<T>(String path, {
    Map<String, dynamic>? params,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.get(path, queryParameters: params);
      return ApiResponse.fromResponse(response, fromJson: fromJson);
    } catch (e) {
      rethrow;
    }
  }

  Future<ApiResponse<T>> post<T>(String path, {
    dynamic data,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.post(path, data: data);
      return ApiResponse.fromResponse(response, fromJson: fromJson);
    } catch (e) {
      rethrow;
    }
  }

  Future<ApiResponse<T>> put<T>(String path, {
    dynamic data,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.put(path, data: data);
      return ApiResponse.fromResponse(response, fromJson: fromJson);
    } catch (e) {
      rethrow;
    }
  }

  Future<ApiResponse<T>> delete<T>(String path, {
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.delete(path);
      return ApiResponse.fromResponse(response, fromJson: fromJson);
    } catch (e) {
      rethrow;
    }
  }

  Future<ApiResponse<T>> patch<T>(String path, {
    dynamic data,
    T Function(dynamic)? fromJson,
  }) async {
    try {
      final response = await _dio.patch(path, data: data);
      return ApiResponse.fromResponse(response, fromJson: fromJson);
    } catch (e) {
      rethrow;
    }
  }
}
